# -*- coding: utf-8 -*-
import hashlib
import json
from datetime import datetime

import requests
from django.conf import settings

from common.mch import handler as mch_handler
from common.timer import TIMER_EVENT_TYPE
from common.timer.handler import submit_notify_event
from common.utils import track_logging
from common.utils.exceptions import ParamError
from common.withdraw import db as withdraw_db
from common.withdraw.model import WITHDRAW_ORDER_STATUS

_LOGGER = track_logging.getLogger('withdraw')

APP_CONF = {
    '100007': {  # 测试
        'API_KEY': 'c712c458c3505a6b0759e458d46e093a',
        'GATEWAY': 'http://18.162.182.119:9001/api/create_withdraw',
        'QUERY_GATEWAY': 'http://18.162.182.119:9001/api/query_withdraw',
    },
    '100003': {  # 正式
        'API_KEY': 'fb14ab136e921ab247b7cc5966887d12',
        'GATEWAY': 'https://api.theflashpay.com/api/create_withdraw',
        'QUERY_GATEWAY': 'https://api.theflashpay.com/api/query_withdraw',
    },
    '100005': {  # 正式 dwc
        'API_KEY': 'fa380c1eb7401162d88da05a79ee300c',
        'GATEWAY': 'https://api.theflashpay.com/api/create_withdraw',
        'QUERY_GATEWAY': 'https://api.theflashpay.com/api/query_withdraw',
    },
}


def _get_api_key(app_id):
    return APP_CONF[app_id]['API_KEY']


def _get_gateway(app_id):
    return APP_CONF[app_id]['GATEWAY']


def _get_query_gateway(app_id):
    return APP_CONF[app_id]['QUERY_GATEWAY']


def generate_sign(parameter, key):
    s = ''
    for k in sorted(parameter.keys()):
        s += '%s=%s&' % (k, parameter[k])
    s += 'key=%s' % key
    _LOGGER.info('flashpay_withdraw sign_str sign: %s' % s)
    m = hashlib.md5()
    m.update(s.encode('utf8'))
    sign = m.hexdigest().lower()
    return sign


def verify_notify_sign(params, key):
    sign = params['sign']
    params.pop('sign')
    calculated_sign = generate_sign(params, key)
    if sign != calculated_sign:
        _LOGGER.info("flashpay_withdraw sign: %s, calculated sign: %s", sign, calculated_sign)
        raise ParamError('sign not pass, data: %s' % params)


def create_order(order, channel):
    app_id = channel.appid
    parameter_dict = {
        "amount": float(order.amount),
        "app_id": app_id,
        "merchant_order_id": str(order.id),
        "notify_url": settings.FLASHPAY_WITHDRAW_NOTIFY_URL + app_id,
        "receive_bank_name": order.pay_account_bank,
        "receive_card_holder": order.pay_account_username,
        "receive_card_number": order.pay_account_num,
        "receive_sub_bank_name": order.pay_account_bank_subbranch or order.pay_account_bank,
    }
    parameter_dict['sign'] = generate_sign(parameter_dict, _get_api_key(app_id))
    # 先设置为三方未知状态
    order.status = WITHDRAW_ORDER_STATUS.THIRD_UNKNOWN
    order.third_type = channel.id
    order.save()
    _LOGGER.info('flashpay_withdraw create data: %s, %s', json.dumps(parameter_dict), _get_gateway(app_id))
    header = {'Content-Type': 'application/json;charset=utf-8'}
    response = requests.post(_get_gateway(app_id), data=json.dumps(parameter_dict),
                             timeout=3, headers=header, verify=False)
    _LOGGER.info('flashpay_withdraw create rsp: %s', response.text)
    data = json.loads(response.text)
    is_success = data.get('status', None)
    pay_id = data.get('merchant_order_id', None)
    if is_success and pay_id:
        order.status = WITHDRAW_ORDER_STATUS.THIRD
        order.third_id = str(pay_id)
        order.extra_info = response.content
        order.save()
        return True
    else:
        order.detail = data.get('error', '')
        order.status = WITHDRAW_ORDER_STATUS.THIRD_FAIL
        order.extra_info = response.content
        order.save()
        return False


def check_notify_sign(request, app_id):
    data = json.loads(request.body)
    _LOGGER.info('data >>>>>>>>>>>>>>>%s' % data)
    api_key = _get_api_key(app_id)
    _LOGGER.info("flashpay_withdraw notify body: %s", request.body)
    verify_notify_sign(data, api_key)
    pay_id = int(data['merchant_order_id'])
    if not pay_id:
        _LOGGER.error("fatal error, mch_order_no not exists, data: %s", data)
        raise ParamError('flashpay_withdraw event does not contain pay ID')
    order = withdraw_db.get_order(pay_id)
    if not order or order.status != WITHDRAW_ORDER_STATUS.THIRD:
        _LOGGER.info('flashpay_withdraw notify order not valid: %s ', pay_id)
        raise ParamError('flashpay_withdraw event order not valid: %s' % pay_id)
    _LOGGER.info('flashpay_withdraw data[status] %s' % data['status'])

    # 1 等待处理，2 处理中，3 成功， 4 失败， 5 成功但已返款
    if data['status'] == 1 or data['status'] == 2:
        order.status = WITHDRAW_ORDER_STATUS.THIRD
        order.extra_info = request.body
        order.third_notify_at = datetime.utcnow()
        order.save()
    elif data['status'] == 4 or data['status'] == 5:
        order.status = WITHDRAW_ORDER_STATUS.THIRD_FAIL
        order.extra_info = request.body
        order.third_notify_at = datetime.utcnow()
        order.save()
    elif data['status'] == 3:
        order.status = WITHDRAW_ORDER_STATUS.DONE
        order.extra_info = request.body
        order.third_notify_at = datetime.utcnow()
        order.save()
        _LOGGER.info("flashpay_withdraw success mch_id: %s, order_id: %s", order.mch_id, order.id)
        notify_success, _ = mch_handler.notify_mch_withdraw(order)
        if not notify_success:
            submit_notify_event(order, TIMER_EVENT_TYPE.MCH_WITHDRAW_NOTIFY)


def query_order(order, channel):
    app_id = channel.appid
    parameter_dict = {
        "app_id": app_id,
        "merchant_order_id": order.third_id,
    }
    parameter_dict['sign'] = generate_sign(parameter_dict, _get_api_key(app_id))
    _LOGGER.info('flashpay_withdraw query_order data: %s', json.dumps(parameter_dict))
    header = {'Content-Type': 'application/json;charset=utf-8'}
    response = requests.post(_get_query_gateway(app_id), data=json.dumps(parameter_dict),
                             timeout=3, headers=header, verify=False)
    _LOGGER.info('flashpay_withdraw create rsp: %s', response.text)
    if response.status_code != 200:
        return
    order = withdraw_db.get_order(order.id)
    data = json.loads(response.text)
    # 1 等待处理，2 处理中，3 成功， 4 失败， 5 成功但已返款
    if data['status'] == 1 or data['status'] == 2:
        order.status = WITHDRAW_ORDER_STATUS.THIRD
        order.extra_info = response.text
        order.save()
    elif data['status'] == 4 or data['status'] == 5:
        order.status = WITHDRAW_ORDER_STATUS.THIRD_FAIL
        order.extra_info = response.text
        order.save()
    elif data['status'] == 3:
        order.status = WITHDRAW_ORDER_STATUS.DONE
        order.extra_info = response.text
        order.save()
        _LOGGER.info("flashpay_withdraw success mch_id: %s, order_id: %s", order.mch_id, order.id)
        notify_success, _ = mch_handler.notify_mch_withdraw(order)
        if not notify_success:
            submit_notify_event(order, TIMER_EVENT_TYPE.MCH_WITHDRAW_NOTIFY)
